## A minimal build system using Bourne sh

Build systems have a tendency to create languages, and their languages have a
way of growing increasingly complex over time.

They work well once you get them working in your environment, but if they
don't work out of the box for some reason, they can be daunting for your users
to debug.

A common source of build errors is incompatibilities between build languages
on different platforms. GNU `make` isn't the same as BSD `make`. `autotools`
can autogenerate `Makefile`s for endless obsolete flavors of Unix, but it
[only serves to hinder you on the platform you're on right now](http://queue.acm.org/detail.cfm?id=2349257).
`cmake` can autogenerate build files for *m* build tools in *n* platforms,
which means it needs to understand *mXn* mappings between DSLs.

An alternative approach is to sidestep existing tools (i.e. `make`) rather
than build atop them. This repo illustrates a way to manage a project using
just plain Bourne `sh`, available on all Unix systems for 30 years. No place
for incompatibilities to rear their heads!

### Interface

Say you have a command to run:

```
cc input1.c input2.c -o output
```

To only do this work when necessary, wrap this command in an `older_than`
block:

```sh
older_than output input1.c input2.c && {
  cc input1 input2 -o output
}
```

If the output is newer than all inputs, nothing happens.

If any of the inputs is newer than the output, the command runs and updates
the output.

A sequence of such blocks can mimic any `makefile`, and the extra verbosity
can help someone debug your project if it doesn't work for them. Every command
is explicit, as is the order to try them in.

### Try it out

To see `older_than` at work and a more complete example of its use, try
running the `build` script in this repo.

```sh
$ ./build
updating a.out
$ ./a.out
hello, world!
$ ./build
# no change to a.out
```

The `build` script is easy to repurpose to your needs. The `older_than`
function in it is 16 lines of code.
